home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
mint
/
filesys
/
ramfs.zoo
/
ramfs.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-08-16
|
27KB
|
1,100 lines
/*
* 'RAMFS': A (resizable) ramdisk file system for MiNT
* Author : Thierry Bousch
* Version: 1.4 (August 1993)
*
* Revision history:
* 1.0 Added version number, and macro-ized TRACE so that it is possible
* to compile with or without debug information.
* 1.1 Added setuid, setgid and sticky bit for directories. Macro-ized
* also DEBUG, ALERT and FATAL.
* 1.2 Deleted open files are now hidden. Added the valid_name() function.
* Added a test in ram_rename about sticky directories.
* 1.3 Deleted open files are now put in a special place (the trash-list)
* instead of leaving them half-deleted in their directories.
* Added support for the FTRUNCATE ioctl call.
* 1.4 Take advantage of the FS_MOUNT call in MiNT 1.08, so that we can
* get rid of drive R. Added FS_LONGPATH support.
* The size of the RAMFILE structure is now considered in the getxattr
* and dfree functions.
*/
#include <string.h>
#include "atarierr.h"
#include "filesys.h"
#define VERSION "1.4"
/*
* You may edit the following constants:
*
* RAM_NAME name of the ramdisk-fs directory
* RAMFILE_MAX maximum length of a filename
* BLKSIZE chunk size (must be a power of two)
*
* Define the symbols NO_{TRACE,DEBUG,ALERT,FATAL} to disable trace,
* debug, alert and fatal calls, respectively.
*/
#define RAM_NAME "U:\\ram"
#define RAMFILE_MAX 35
#define BLKSIZE 512L
#define NO_TRACE
/*
* this points to the structure that has all the useful functions that
* the kernel told us about
*/
struct kerinfo *kernel;
#define CCONWS (*kernel->dos_tab[0x09])
#define DCNTL (*kernel->dos_tab[0x130])
#define Timestamp (*kernel->dos_tab[0x2c])
#define Datestamp (*kernel->dos_tab[0x2a])
#define FreeMemory() (*kernel->dos_tab[0x48])(-1L)
#define Getpid (*kernel->dos_tab[0x10b])
#define Getuid (*kernel->dos_tab[0x10f])
#define Getgid (*kernel->dos_tab[0x114])
#define Geteuid (*kernel->dos_tab[0x138])
#define Getegid (*kernel->dos_tab[0x139])
#define Kmalloc (*kernel->kmalloc)
#define Kfree (*kernel->kfree)
#define Stricmp (*kernel->stricmp)
#define Denyshare (*kernel->denyshare)
#ifndef NULL
# define NULL ((void *)0L)
#endif
#define FTRUNCATE (('F'<< 8) | 4) /* from the Minix FS */
/* Useful macros */
#define IS_DIRECTORY(s) (((s)->mode & S_IFMT) == S_IFDIR)
#define IS_SYMLINK(s) (((s)->mode & S_IFMT) == S_IFLNK)
#define IS_SETUID(s) ((s)->mode & S_ISUID)
#define IS_SETGID(s) ((s)->mode & S_ISGID)
#define IS_STICKY(s) ((s)->mode & S_ISVTX)
/* Conditional debugging */
#ifdef NO_DEBUG
# define DEBUG(x)
#else
# define DEBUG(x) (*kernel->debug)x
#endif
#ifdef NO_ALERT
# define ALERT(x)
#else
# define ALERT(x) (*kernel->alert)x
#endif
#ifdef NO_TRACE
# define TRACE(x)
#else
# define TRACE(x) (*kernel->trace)x
#endif
#ifdef NO_FATAL
# define FATAL(x)
#else
# define FATAL(x) (*kernel->fatal)x
#endif
/* Forward declarations of the file system functions */
long ram_root (int drv, fcookie *fc);
long ram_lookup (fcookie *dir, char *name, fcookie *fc);
long ram_creat (fcookie *dir, char *name, unsigned mode,
int attrib, fcookie *fc);
DEVDRV* ram_getdev (fcookie *fc, long *devsp);
long ram_getxattr (fcookie *fc, XATTR *xattr);
long ram_chattr (fcookie *fc, int attrib);
long ram_chown (fcookie *fc, int uid, int gid);
long ram_chmode (fcookie *fc, unsigned mode);
long ram_mkdir (fcookie *fc, char *name, unsigned mode);
long ram_rmdir (fcookie *dir, char *name);
long ram_remove (fcookie *dir, char *name);
long ram_getname (fcookie *root, fcookie *dir, char *path, int size);
long ram_rename (fcookie *olddir, char *oldname,
fcookie *newdir, char *newname);
long ram_opendir (DIR *dirh, int flags);
long ram_readdir (DIR *dirh, char *nm, int nmlen, fcookie *fc);
long ram_rewinddir (DIR *dirh);
long ram_closedir (DIR *dirh);
long ram_pathconf (fcookie *dir, int which);
long ram_dfree (fcookie *dir, long *buf);
long ram_writelabel (fcookie *dir, char *name);
long ram_readlabel (fcookie *dir, char *name, int namelen);
long ram_symlink (fcookie *dir, char *name, char *to);
long ram_readlink (fcookie *dir, char *buf, int len);
long ram_hardlink (fcookie *fromdir, char *fromname,
fcookie *todir, char *toname);
long ram_fscntl (fcookie *dir, char *name, int cmd, long arg);
long ram_dskchng (int drv);
/* Forward declarations of the device driver functions */
long ram_open (FILEPTR *f);
long ram_write (FILEPTR *f, char *buf, long bytes);
long ram_read (FILEPTR *f, char *buf, long bytes);
long ram_lseek (FILEPTR *f, long where, int whence);
long ram_ioctl (FILEPTR *f, int mode, void *buf);
long ram_datime (FILEPTR *f, int *time, int rwflag);
long ram_close (FILEPTR *f, int pid);
long ram_select (FILEPTR *f, long p, int mode);
void ram_unselect (FILEPTR *f, long p, int mode);
/*
* Here is the structure used for ram files. The "next" field points to
* the following file/dir in that directory. The "up" field points to the
* directory the file/dir is in, or NULL for the root directory. The
* "down" field is only used by subdirectories and points to the first
* entry in that subdirectory. "lst" is the list of open FILEPTRs for
* this file. "length" is the actual length, "data" the actual data, and
* "avail" is the length of the ram block allocated for "data".
*
* Note that all the memory is allocated in one block: it may cause trouble
* with big files if the memory is fragmented.
*/
typedef struct ramfile {
struct ramfile *next, *up, *down;
char filename[RAMFILE_MAX+1];
int uid, gid;
short time, date;
unsigned mode;
FILEPTR *lst;
long length, avail;
char *data;
} RAMFILE;
RAMFILE ramroot, *trash;
int ram_drive;
DEVDRV ram_device = {
ram_open, ram_write, ram_read, ram_lseek, ram_ioctl, ram_datime,
ram_close, ram_select, ram_unselect
};
FILESYS ram_filesys = {
(FILESYS *)0,
FS_LONGPATH,
ram_root,
ram_lookup, ram_creat, ram_getdev, ram_getxattr,
ram_chattr, ram_chown, ram_chmode,
ram_mkdir, ram_rmdir, ram_remove, ram_getname, ram_rename,
ram_opendir, ram_readdir, ram_rewinddir, ram_closedir,
ram_pathconf, ram_dfree,
ram_writelabel, ram_readlabel, ram_symlink, ram_readlink,
ram_hardlink, ram_fscntl, ram_dskchng
};
struct fs_descr ram_fs_descr = { &ram_filesys };
/*
* This function is called by the kernel when the
* file system is being loaded, and should return the file system
* structure
*/
FILESYS *ram_init (struct kerinfo *k)
{
kernel = k;
CCONWS("Ramdisk filesystem for MiNT (Version " VERSION ", compiled "
__DATE__ ") by T.Bousch\r\n");
TRACE(("ram_init: initialize filesystem"));
ramroot.next = ramroot.up = ramroot.down = NULL;
ramroot.filename[0] = 0;
ramroot.uid = ramroot.gid = 0;
ramroot.time = Timestamp();
ramroot.date = Datestamp();
ramroot.mode = S_IFDIR | DEFAULT_DIRMODE;
ramroot.lst = NULL;
ramroot.length = ramroot.avail = 0;
ramroot.data = NULL;
trash = NULL;
/*
* We try first to install the filesystem as a gemdos-only drive
* because we don't want to pollute the bios drive map with a fake
* drive. Unfortunately, this will only work with recent MiNT
* versions (at least 1.08); with older versions we fallback
* to the previous method (install drive 'R').
*/
if (DCNTL(FS_INSTALL, RAM_NAME, &ram_fs_descr) >= 0 &&
DCNTL(FS_MOUNT, RAM_NAME, &ram_fs_descr) >= 0) {
ram_drive = ram_fs_descr.dev_no;
/* Tell the kernel that the filesystem is already loaded */
return (FILESYS*)(1L);
}
/* Add drive 'R' to the list of Bios drives */
ram_drive = 'R'-'A';
*(unsigned long *)(0x4c2L) |= (1UL << ram_drive);
return &ram_filesys;
}
long ram_root (int drv, fcookie *fc)
{
if (drv == ram_drive) {
TRACE(("ram_root: drive #%d is a ramdisk", drv));
fc->fs = &ram_filesys;
fc->dev = drv;
fc->index = (long) &ramroot;
return 0;
} else {
fc->fs = NULL; /* Not our drive */
return EDRIVE;
}
}
long ram_lookup (fcookie *dir, char *name, fcookie *fc)
{
RAMFILE *s, *d;
TRACE(("ram